﻿using System;
using System.Diagnostics;
using System.IO;
using System.Threading;
using System.Windows;
using DataServer.Config;
using DataServer.Dao;
using log4net;

namespace DataServer
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App 
    {
        private static ILog _log;
        private readonly string mysqlpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DataServer.Properties.Resources.mysqlpath);
        private  readonly string proxypath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DataServer.Properties.Resources.proxypath);
        // ReSharper disable once NotAccessedField.Local
        private static Mutex _mutex;
        private bool _is64Bit = Environment.Is64BitOperatingSystem;
        static readonly object synObj = new object();
        private bool _conflict = false;


        public App()
        {
            Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
        }

        #region 异常处理

        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            if (e.ExceptionObject is Exception ex)
            {
                string temp = e.IsTerminating ? "已" : "未";
                _log.Error($"当前域未处理异常：{ex.Message} 程序{temp}关闭。");//来源:{ex.StackTrace}
            }
        }

        private void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            _log.Error($"UI线程未处理异常：{e.Exception.Message}   来源:{e.Exception.StackTrace}");
            e.Handled = true;//使用这一行代码告诉运行时，该异常被处理了，不再作为UnhandledException抛出了。
        }

        #endregion

        protected override void OnStartup(StartupEventArgs e)
        {
            if (HaInstance()) // 单实例
            {
                _conflict = true;
                return;
            }

            //ConfigManager.UpdateServiceWcfConfig(ConfigManager.GetDefaultIp(), 80); // 更新WCF服务地址为实际IP地址
           
            //StopMysql();
            if (!FindProcess("mysqld"))
            {
                StartMysql();
                Thread.Sleep(500);
            }
           
            string sysbit = _is64Bit ? "client_x64" : "client_x86";
            if (!FindProcess(sysbit))
            {
                StartProxy();
            }
          
            log4net.Config.XmlConfigurator.Configure();
            _log = LogManager.GetLogger(typeof(App));
            // 初始化Dapper 的映射
            DapperExtensions.DapperExtensions.SetMappingAssemblies(new[]
            {
                typeof(DeviceMapper).Assembly,
                typeof(DeviceCategoryMapper).Assembly,
                typeof(DeviceTypeMapper).Assembly,
                typeof(OperationMapper).Assembly,
                typeof(ChannelMapper).Assembly,
                typeof(DataItemMapper).Assembly,
                typeof(RemoteItemDao).Assembly,
                typeof(UserMapper).Assembly,
                typeof(ResourceDao).Assembly

            });
            var uri = new Uri("/PresentationFramework.Aero, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35;component/themes/aero.normalcolor.xaml", UriKind.Relative);
            Current.Resources.Source = uri;
            base.OnStartup(e);
        }

        protected override void OnExit(ExitEventArgs e)
        {
            if (_conflict)
            {
                base.OnExit(e);
                return;
            }
            try
            {
                StopProcess("mysqld");
                string sysbit = _is64Bit ? "client_x64" : "client_x86";
                StopProcess(sysbit);
                if (e.ApplicationExitCode != 0)
                {
                    _log.Warn($"系统异常退出,异常码{e.ApplicationExitCode}");
                    // 异常退出时自动重启
                    Process p = new Process();
                    p.StartInfo.FileName = AppDomain.CurrentDomain.BaseDirectory + AppDomain.CurrentDomain.FriendlyName;
                    p.StartInfo.UseShellExecute = false;
                    p.Start();
                }
            }
            catch
            { 
            }
            base.OnExit(e);
        }

        /// <summary>
        /// 检查
        /// </summary>
        /// <returns></returns>
        private bool HaInstance()
        {
            try
            {
                lock (synObj)
                {
                    bool flag = true;

                    try
                    {
                        _mutex = Mutex.OpenExisting("RelationMutex");
                    }
                    catch (WaitHandleCannotBeOpenedException)
                    {
                        _mutex = new Mutex(true, "RelationMutex");
                        flag = false;
                    }
                    if (flag)
                    {
                        _mutex = null;
                        MessageBox.Show("程序已经在运行!", "提示",MessageBoxButton.OK, MessageBoxImage.Warning);
                        Current.Shutdown(1);
                        return true;
                    }
                }
            }
            catch (Exception exception)
            {
                MessageBox.Show("异常:"+exception.Message, "提示", MessageBoxButton.OK, MessageBoxImage.Error);
                Current.Shutdown(1);
                return true;
            }
            return false;
        }
        /// <summary>
        /// 启动Mysql数据库服务
        /// </summary>
        private void StartMysql()
        {
            try
            {
                Process proc = new Process
                {
                    StartInfo =
                    {
                        WorkingDirectory = mysqlpath,
                        FileName = Path.Combine(mysqlpath,"bin", "mysqld.exe"),
                        Arguments = " --default-character-set=gbk",
                        UseShellExecute = false,
                        CreateNoWindow = true,
                        RedirectStandardOutput = true
                    }
                };
                proc.Start();
            }
            catch (Exception ex)
            {
               Console.WriteLine(ex.Message);
            }
        }
        private void StartProxy()
        {
            try
            {
                bool allow  =   ConfigManager.GetValueFromIni("网络访问", "允许外网", false);
                if(!allow) return;
                string ip = ConfigManager.GetValueFromIni("网络访问", "外网IP", "47.98.168.237");
                int port = ConfigManager.GetValueFromIni("网络访问", "端口", 4900);
                string key = ConfigManager.GetValueFromIni("网络访问", "密钥", "");
                string sysbit = _is64Bit ? "client_x64.exe" : "client_x86.exe";
                Process proc = new Process
                {
                    StartInfo =
                    {
                        WorkingDirectory = proxypath,
                        FileName = Path.Combine(proxypath, sysbit),
                        Arguments = $" -s {ip} -p {port} -k {key}",
                        UseShellExecute = false,
                        CreateNoWindow = true,
                        RedirectStandardOutput = true
                    }
                };
                proc.Start();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        /// <summary>
        /// 关闭Mysql数据库服务
        /// </summary>
        private void StopProcess(string name)
        {
            try
            {
                Process[] pro = Process.GetProcesses();
                //遍历所有查找到的进程
                for (int i = 0; i < pro.Length; i++)
                {
                    //判断此进程是否是要查找的进程
                    if (pro[i].ProcessName.Contains(name))
                    {
                        pro[i].Kill();
                        return;
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }
        /// <summary>
        /// 检查Mysql数据库服务是否已经启动
        /// </summary>
        /// <returns></returns>
        private bool FindProcess(string name)
        {
            Process[] pro = Process.GetProcesses();
            //遍历所有查找到的进程
            for (int i = 0; i < pro.Length; i++)
            {
                //判断此进程是否是要查找的进程
                if (pro[i].ProcessName.Contains(name))
                {
                    return true;
                }
            }
            return false;
        }


    }
}
